package com.katian.etat_compte;

import com.katian.FileInfo;
import com.katian.FileMeta;
import com.katian.UploadFiles;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Controller
@RequestMapping("/etat-compte")
public class EtatCompteController {
    public static final String RESULT_FILE_NAME = "etat-comptes.xlsx";
    protected final Log logger = LogFactory.getLog(getClass());

    public static final String ACHAT = "achat";
    public static final String COMMISSION = "commission";
    public static final String ETAT_COMPTE = "etat_compte";
    public static final String VENTES_BUY_BACK = "ventes_buy_back";
    public static final String LISTE_PRODUITS = "liste_produits";
    public static final String TAUX_DISTRIBUTEURS = "taux_distributeurs";
    public static final String RESULT = "result";
    public static final String RESULT_URL = "result_url";


    @RequestMapping(method = RequestMethod.GET)
    public String printWelcome(ModelMap model) {
        model.addAttribute(ACHAT, getAchatFileName());
        model.addAttribute(COMMISSION, getCommissionFileName());
        model.addAttribute(ETAT_COMPTE, getEtatCompteFileName());
        model.addAttribute(VENTES_BUY_BACK, getVentesBuyBackFileName());
        model.addAttribute(LISTE_PRODUITS, getListeProduitsFileName());
        model.addAttribute(TAUX_DISTRIBUTEURS, getTauxDistributeurFileName());
        model.addAttribute(RESULT, getResultFileName());
        return "etat-compte";
    }

    @RequestMapping(value = "/generate", method = RequestMethod.GET)
    @ResponseBody
    public String generate() throws Exception {
        try {
            String folderPath = getFilePath(RESULT);
            File folder = new File(folderPath);
            if (folder.exists()) {
                FileUtils.cleanDirectory(folder);
            } else {
                FileUtils.forceMkdir(folder);
            }

            InputStream commisionInput = new FileInputStream(getFile(COMMISSION));
            System.out.println("Get Commission Items");
            Map<String, CommissionItem> commisionItemMap = MergerUtil.getCommissionItem(commisionInput);

            System.out.println("Get Products");
            InputStream inputStream = new FileInputStream(getFile(LISTE_PRODUITS));
            Map<Long, Produit> products = MergerUtil.getProducts(inputStream);

            System.out.println("Get Achats");
            inputStream = new FileInputStream(getFile(ACHAT));
            Map<String, Achat> achats = MergerUtil.getAchats(inputStream);


            System.out.println("Get Vente");
            inputStream = new FileInputStream(getFile(VENTES_BUY_BACK));
            Map<String, Commande> ventes = MergerUtil.getVentes(inputStream, products);

            System.out.println("Get Distributeurs");
            inputStream = new FileInputStream(getFile(TAUX_DISTRIBUTEURS));
            Map<String, Distributeur> distributeurs = MergerUtil.getDistributeurs(inputStream);


            InputStream etatCompteInput = new FileInputStream(getFile(ETAT_COMPTE));

            System.out.println("Loading etat de compte");
            XSSFWorkbook wb = new XSSFWorkbook(etatCompteInput);
            XSSFWorkbook wbDestination = new XSSFWorkbook();

            String customerName = MergerUtil.getCustomerName(wb);
            String period = MergerUtil.getPeriod(wb);

            System.out.println("Generate Commission");
            MergerUtil.generateCommision(wb, wbDestination, commisionItemMap);

            System.out.println("Generate BuyBack");
            MergerUtil.generateBuyBack(wb, wbDestination, commisionItemMap, ventes, distributeurs);

            System.out.println("Generate Achat");
            MergerUtil.generateAchat(wb, wbDestination, achats);


            System.out.println("Generate UnconfirmedBS");
            MergerUtil.generateUnconfirmedBS(wb, wbDestination);

            System.out.println("Generate UnconfirmedBB");
            MergerUtil.generateUnconfirmedBB(wb, wbDestination);

            File file = new File(folder.getAbsolutePath() + File.separator + com.katian.FileUtils.getValidFileName(customerName + " " + period + ".xlsx"));

            System.out.println("Write file to: " + file.getAbsolutePath());
            wbDestination.write(new FileOutputStream(file));
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }


        return "cool";
    }


    @RequestMapping(value = "/get.achat.file.name", method = RequestMethod.GET)
    @ResponseBody
    public FileInfo getAchatFileName() {
        return getFileName(ACHAT);
    }

    @RequestMapping(value = "/get.commission.file.name", method = RequestMethod.GET)
    @ResponseBody
    public FileInfo getCommissionFileName() {
        return getFileName(COMMISSION);
    }

    @RequestMapping(value = "/get.etat.compte.file.name", method = RequestMethod.GET)
    @ResponseBody
    public FileInfo getEtatCompteFileName() {
        return getFileName(ETAT_COMPTE);
    }

    @RequestMapping(value = "/get.ventes.buy.back.file.name", method = RequestMethod.GET)
    @ResponseBody
    public FileInfo getVentesBuyBackFileName() {
        return getFileName(VENTES_BUY_BACK);
    }

    @RequestMapping(value = "/get.liste.produits.file.name", method = RequestMethod.GET)
    @ResponseBody
    public FileInfo getListeProduitsFileName() {
        return getFileName(LISTE_PRODUITS);
    }

    @RequestMapping(value = "/get.taux.distributeurs.file.name", method = RequestMethod.GET)
    @ResponseBody
    public FileInfo getTauxDistributeurFileName() {
        return getFileName(TAUX_DISTRIBUTEURS);
    }

    @RequestMapping(value = "/get.result.file.name", method = RequestMethod.GET)
    @ResponseBody
    public FileInfo getResultFileName() {
        return getFileName(RESULT);
    }

    @RequestMapping(value = "/get.result.file", method = RequestMethod.GET)
    public void getResultFile(HttpServletResponse response) throws IOException {
        FileInfo resultFileName = getResultFileName();
        if (resultFileName != null) {
            File resultFile = new File(getFilePath(RESULT) + File.separator + resultFileName.getFileName());
            if (resultFile.exists()) {
                response.setContentType("application-xdownload");
                response.setHeader("Content-Disposition", "attachment; filename=\"" + resultFile.getName() + "\"");

                FileInputStream fileInputStream = new FileInputStream(resultFile);
                IOUtils.copy(fileInputStream, response.getOutputStream());
                fileInputStream.close();
                response.flushBuffer();

            }
        }
    }

    @RequestMapping(value = "/upload.achat", method = RequestMethod.POST)
    @ResponseBody
    public List<FileMeta> uploadAchat(@ModelAttribute(value = "FORM") UploadFiles files, BindingResult result) {
        return handleNewFile(files, result, ACHAT);
    }

    @RequestMapping(value = "/upload.commission", method = RequestMethod.POST)
    @ResponseBody
    public List<FileMeta> uploadCommission(@ModelAttribute(value = "FORM") UploadFiles files, BindingResult result) {
        return handleNewFile(files, result, COMMISSION);
    }

    @RequestMapping(value = "/upload.etat.compte", method = RequestMethod.POST)
    @ResponseBody
    public List<FileMeta> uploadEtatCompte(@ModelAttribute(value = "FORM") UploadFiles files, BindingResult result) {
        return handleNewFile(files, result, ETAT_COMPTE);
    }

    @RequestMapping(value = "/upload.ventes.buy.back", method = RequestMethod.POST)
    @ResponseBody
    public List<FileMeta> uploadVentesBuyBack(@ModelAttribute(value = "FORM") UploadFiles files, BindingResult result) {
        logger.info("received file: " + files.getFile().getOriginalFilename());
        return handleNewFile(files, result, VENTES_BUY_BACK);
    }

    @RequestMapping(value = "/upload.liste.produits", method = RequestMethod.POST)
    @ResponseBody
    public List<FileMeta> uploadListeProduits(@ModelAttribute(value = "FORM") UploadFiles files, BindingResult result) {
        return handleNewFile(files, result, LISTE_PRODUITS);
    }

    @RequestMapping(value = "/upload.taux.distributeurs", method = RequestMethod.POST)
    @ResponseBody
    public List<FileMeta> uploadTauxDistributeurs(@ModelAttribute(value = "FORM") UploadFiles files, BindingResult result) {
        return handleNewFile(files, result, TAUX_DISTRIBUTEURS);
    }


    private File getFile(String folderName) {
        File file = null;
        String folderPath = getFilePath(folderName);
        File folder = new File(folderPath);
        if (folder.exists()) {
            File[] files = folder.listFiles();
            if (files != null && files.length > 0) {
                file = files[0];
            }
        }
        return file;
    }

    private FileInfo getFileName(String folderName) {
        FileInfo info = new FileInfo();
        File file = getFile(folderName);
        if (file != null) {
            info.setFileName(file.getName());
        }
        return info;
    }

    private List<FileMeta> handleNewFile(UploadFiles files, BindingResult result, String folderName) {
        List<FileMeta> fileMetas = null;
        if (!result.hasErrors()) {
            try {
                String folderPath = getFilePath(folderName);
                File folder = new File(folderPath);
                if (folder.exists()) {
                    FileUtils.cleanDirectory(folder);
                } else {
                    FileUtils.forceMkdir(folder);
                }

                CommonsMultipartFile multipartFile = files.getFile();

                FileMeta fileMeta = new FileMeta();
                fileMeta.setFileName(multipartFile.getName());
                fileMeta.setFileType(multipartFile.getContentType());
                fileMeta.setFileSize(multipartFile.getSize() / 1024 + " Kb");
                if (fileMetas == null) {
                    fileMetas = new ArrayList<>();
                }
                fileMetas.add(fileMeta);

                String filePath = folderPath + File.separator + com.katian.FileUtils.getValidFileName(multipartFile.getOriginalFilename());

                File file = new File(filePath);
                multipartFile.getFileItem().write(file);
            } catch (Exception e) {
                logger.error("Can't save file", e);
            }
        }

        return fileMetas;
    }


    private String getFilePath(String fileName) {
        return System.getProperty("java.io.tmpdir") + File.separator + "etat-compte" + File.separator + fileName;
    }
}